#ifndef win32api_HPP__
#define win32api_HPP__

#include <boost/config.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/range/iterator_range.hpp>

#include "os_version.hpp"


#ifdef BOOST_WINDOWS
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>				//Link to Secur32.lib
#else
#error Not defined yet for OS != Windows
#endif


namespace detail
{

//void init_os_version( os_version & osv )
//{
//	osv.major = 0;
//	osv.minor = 0;
//	osv.build_number = 0;
//	osv.unknown = 0x0f000000;
//}

ntlm::os_version get_system_os_version()
{
	ntlm::os_version temp;
	//init_os_version(temp);

#ifdef BOOST_WINDOWS

	OSVERSIONINFO osvi;

	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

	BOOL ret = GetVersionEx(&osvi);

	if ( ret != 0 )
	{
		temp.major = osvi.dwMajorVersion;
		temp.minor = osvi.dwMinorVersion;
		temp.build_number = osvi.dwBuildNumber;
	}
	else
	{
		throw std::runtime_error("Win32Api GetVersionEx() error");
	}
#else
#error Not defined yet for OS != Windows
#endif

	return temp;
}

std::string get_computer_name( COMPUTER_NAME_FORMAT name_type )
{
#ifdef BOOST_WINDOWS

	TCHAR buffer[256] = "";	//TEXT("");
	DWORD size = sizeof(buffer);

	BOOL ret = ::GetComputerNameEx(name_type, buffer, &size);

	if ( ret == 0 )
	{
		//_tprintf(TEXT("GetComputerNameEx failed (%d)\n"), GetLastError());
		throw std::runtime_error("Win32Api GetComputerNameEx() error");
		//return "";
	}
	else 
	{
		return std::string (buffer);
	}
#else
#error Not defined yet for OS != Windows
#endif
}

std::string get_workstation_name()
{
#ifdef BOOST_WINDOWS

	return get_computer_name(ComputerNamePhysicalDnsHostname);

	//   TCHAR buffer[256] = "";	//TEXT("");
	//DWORD size = sizeof(buffer);
	//   
	//BOOL ret = GetComputerNameEx(ComputerNamePhysicalDnsHostname, buffer, &size);

	//   if ( ret == 0 )
	//   {
	//       //_tprintf(TEXT("GetComputerNameEx failed (%d)\n"), GetLastError());
	//	throw std::runtime_error("Win32Api GetVersionEx() error");
	//       //return "";
	//   }
	//   else 
	//{
	//	return std::string (buffer);
	//}


	////boost::to_upper(str);
	////std::string xxx = boost::to_upper_copy("Hello World");

	//
	//   std::string str1("HeLlO WoRld!");
	//   boost::to_upper(str1); // str1=="HELLO WORLD!"

	//std::string str2 = boost::to_upper_copy(str1);
	//std::string str3 = boost::to_upper_copy( std::string("hola") );

#else
#error Not defined yet for OS != Windows
#endif
}

std::string get_domain_name()
{
#ifdef BOOST_WINDOWS
	return get_computer_name(ComputerNamePhysicalDnsDomain);
#else
#error Not defined yet for OS != Windows
#endif
}


std::string get_user_domain_name()
{
#ifdef BOOST_WINDOWS
	using boost::algorithm::split_iterator;
	using boost::algorithm::make_split_iterator;
	using boost::algorithm::first_finder;
	using boost::algorithm::is_iequal;
	using boost::copy_range;
	

	char user_name[256];			// null terminated char array (C-Style String)
	DWORD user_name_size = 256;
	BOOL ret = ::GetUserNameEx(NameSamCompatible, user_name, &user_name_size);

	if ( ret == 0 )
	{
		throw std::runtime_error("Win32Api GetUserNameEx() error");
	}
	else 
	{
		typedef split_iterator<char*> cstring_split_iterator;

		cstring_split_iterator it = make_split_iterator(user_name, first_finder("\\", is_iequal()));
		cstring_split_iterator end;

		if ( it != end)
		{
			return copy_range<std::string>(*it);
		}

		return "";
	}

#else
#error Not defined yet for OS != Windows
#endif

	//C# Version

	//D:\Users\fernando.pelliccioni\Documents\RefSrc\Source\Windows 7 SP1 Netfx\3.5.1\DEVDIV\depot\DevDiv\releases\whidbey\Win7SP1\ndp\clr\src\BCL\System\Environment.cs\1\Environment.cs
	//if (OSVersion.Platform == PlatformID.Win32NT) {
	//	ret =  Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
	//	if (ret == 1) { 
	//		string samName = domainName.ToString();
	//		int index = samName.IndexOf('\\'); 
	//		if( index != -1) { 
	//			return samName.Substring(0, index);
	//		} 
	//	}
	//	domainNameLen = domainName.Capacity;
	//}

}






} //namespace detail



#endif // win32api_HPP__